﻿/*
   Open Intel 
   Copyright © 2011 – ISC. All Rights Reserved.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ISC.MapDotNetServer.Common.Maps;

namespace OI.Framework
{
    // these are where clause filters applied to a layer
    // arrays of comma separated records are on the Layer metadata (Filters)
    public class FilterItem
    {
        // name of filter displayed to user
        public string Name { get; set; }

        // optional group name to display radiobutton list for selecting one of several filters (null uses a checkbox)
        public string XorGroup { get; set; }

        // Layer filter string
        public string Where { get; set; }

        // is this filter enabled
        public bool IsEnabled { get; set; }

        // optional context sensitive parameter
        public string Param { get; set; }


        // parses Layer metadata and return collection of filters
        public static IList<FilterItem> ParseFilterItems(Layer layer)
        {
            if (layer != null && 
                layer.MetaData.ContainsKey(Configuration.FiltersMetaKey))
            {
                return ParseFilterItems(layer.MetaData[Configuration.FiltersMetaKey]);
            }

            return new List<FilterItem>();
        }


        // parses metadata string and return collection of filters
        public static IList<FilterItem> ParseFilterItems(string filterStr)
        {
            var filters = new List<FilterItem>();

            string[] filterArray = filterStr.Split('$');
            filters.AddRange(from f in filterArray
                             select f.Split(',')
                             into newFIArray
                             where newFIArray.Length == 5
                             select new FilterItem
                             {
                                Name = newFIArray[0],
                                XorGroup = newFIArray[1],
                                Where = newFIArray[2],
                                IsEnabled = Convert.ToBoolean(newFIArray[3]),
                                Param = newFIArray[4]
                             });
            return filters;
        }


        // serialize this
        public string Serialize()
        {
            return Name + "," + XorGroup + "," + Where + "," + IsEnabled + "," + Param;
        }


        // serialize filter items
        public static string SerialzeFilterItems(IList<FilterItem> filterItems)
        {
            var sb = new StringBuilder();
            foreach (var f in filterItems)
            {
                sb.Append(f.Name + "," + f.XorGroup + "," + f.Where + "," + f.IsEnabled + "," + f.Param + "$");
            }
            return sb.ToString().Trim('$');
        }


        // creates a human-readable string describing the active filters
        public static string CreateDisplayHeader(IList<FilterItem> filterItems)
        {
            var sb = new StringBuilder();
            foreach (var f in filterItems.Where(f => f.IsEnabled && !string.IsNullOrEmpty(f.Where)))
            {
                sb.Append(f.Name + ", ");
            }
            return sb.ToString().Trim(' ').Trim(',');
        }


        // apply the supplied filters to the supplied layer
        // return true if changed
        public static bool ApplyFilterToLayer(IList<FilterItem> filterItems, Layer layer)
        {
            // update the metadata on the layer so it is in-snyc with the filter items
            layer.MetaData[Configuration.FiltersMetaKey] = SerialzeFilterItems(filterItems);

            // if we have no filter items, then we should restore layer to baseline and exit
            if (filterItems.Count == 0)
            {
                layer.LayerState = Layer.LayerStates.Baseline;
                return true;
            }

            // grab current where clause 
            string oldWhere = layer.ConnectionSpecification.WhereClause;

            // iterate enabled filters and build where clause
            var sb = new StringBuilder();
            foreach (var f in filterItems.Where(f => f.IsEnabled && !string.IsNullOrEmpty(f.Where)))
            {
                string where = f.Where;

                // check for {NOW} special placeholder
                if (where.Contains("{NOW}"))
                {
                    int days = Convert.ToInt32(f.Param);
                    string dateStr = DateTime.Now.AddDays(days).ToShortDateString();
                    where = where.Replace("{NOW}", dateStr);
                }

                sb.Append(where + " AND ");
            }

            // scrub end
            string w = sb.ToString();
            string newWhere = w.Length > 5 ? w.Substring(0, w.Length - 5) : w;

            // if the filter changed
            if (oldWhere != newWhere)
            {
                layer.ConnectionSpecification.WhereClause = newWhere;

                // we are modifying the where clause but not the classification symbology
                layer.LayerState = Layer.LayerStates.Modified;
                foreach (var c in layer.Classifications)
                {
                    c.ClassificationState = Classification.ClassificationStates.Baseline;
                }

                return true;
            }
            return false;
        }


        // this method will ensure only one in the XOR group is enabled
        // if the changeItem is set to false, will look for an item with an empty where clause
        public static void XorFilter(IList<FilterItem> filterItems, FilterItem changeItem)
        {
            if (changeItem.IsEnabled)
            {
                foreach (var f in filterItems.Where(f => f.XorGroup == changeItem.XorGroup && f != changeItem))
                {
                    f.IsEnabled = false;
                }
            }
            else
            {
                var all = filterItems.FirstOrDefault(f => !string.IsNullOrEmpty(f.Where));
                if (all != null)
                {
                    all.IsEnabled = true;
                }
            }
        }
    }
}
